home *** CD-ROM | disk | FTP | other *** search
- /* Events: printing them, converting them to and from characters.
- Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-
- This file is part of XEmacs.
-
- XEmacs is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- XEmacs is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
-
- You should have received a copy of the GNU General Public License
- along with XEmacs; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* Synched up with: Not in FSF. */
-
- /* This file has been Mule-ized. */
-
- #include <config.h>
- #include "lisp.h"
- #include "buffer.h"
- #include "window.h"
- #include "device.h"
- #include "device-tty.h" /* for stuff in character_to_event */
- #include "device-x.h" /* for x_event_name prototype */
- #include "frame.h"
- #include "events.h"
- #include "keymap.h"
- #include "extents.h" /* Just for the EXTENTP abort check... */
- #include "redisplay.h"
-
- /* Where old events go when they are explicitly deallocated.
- The event chain here is cut loose before GC, so these will be freed
- eventually.
- */
- static struct Lisp_Event *event_resource;
-
- Lisp_Object Qeventp;
- Lisp_Object Qevent_live_p;
- Lisp_Object Qkey_press_event_p;
- Lisp_Object Qbutton_event_p;
- Lisp_Object Qmouse_event_p;
- Lisp_Object Qprocess_event_p;
-
- /* #### Ad-hoc hack. Should be part of define_lrecord_implementation */
- void
- clear_event_resource (void)
- {
- event_resource = 0;
- }
-
- static Lisp_Object mark_event (Lisp_Object, void (*) (Lisp_Object));
- static void print_event (Lisp_Object, Lisp_Object, int);
- static int event_equal (Lisp_Object, Lisp_Object, int);
- static unsigned long event_hash (Lisp_Object obj, int depth);
- DEFINE_LRECORD_IMPLEMENTATION ("event", event,
- mark_event, print_event, 0, event_equal,
- event_hash, struct Lisp_Event);
-
- /* Make sure we lose quickly if we try to use this event */
- static void
- deinitialize_event (struct Lisp_Event *event)
- {
- int i;
-
- for (i = 0; i < ((sizeof (struct Lisp_Event)) / sizeof (int)); i++)
- ((int *) event) [i] = 0xdeadbeef;
- event->event_type = dead_event;
- event->device = Qnil;
- set_lheader_implementation (&(event->lheader), lrecord_event);
- event_next (event) = 0;
- }
-
- static Lisp_Object
- mark_event (Lisp_Object obj, void (*markobj) (Lisp_Object))
- {
- struct Lisp_Event *event = XEVENT (obj);
-
- switch (event->event_type)
- {
- case key_press_event:
- ((markobj) (event->event.key.keysym));
- break;
- case process_event:
- ((markobj) (event->event.process.process));
- break;
- case timeout_event:
- ((markobj) (event->event.timeout.function));
- ((markobj) (event->event.timeout.object));
- break;
- case eval_event:
- case misc_user_event:
- ((markobj) (event->event.eval.function));
- ((markobj) (event->event.eval.object));
- break;
- case button_press_event:
- case button_release_event:
- case pointer_motion_event:
- case magic_event:
- case empty_event:
- case dead_event:
- break;
- default:
- abort ();
- }
- ((markobj) (event->channel));
- ((markobj) (event->device));
- event = event_next (event);
- if (!event)
- return (Qnil);
- XSETEVENT (obj, event);
- return (obj);
- }
-
- static void
- print_event_1 (CONST char *str, Lisp_Object obj, Lisp_Object printcharfun)
- {
- char buf[255];
- write_c_string (str, printcharfun);
- format_event_object (buf, XEVENT (obj), 0);
- write_c_string (buf, printcharfun);
- }
-
- static void
- print_event (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
- {
- if (print_readably)
- error ("printing unreadable object #<event>");
-
- switch (XEVENT (obj)->event_type)
- {
- case key_press_event:
- print_event_1 ("#<keypress-event ", obj, printcharfun);
- break;
- case button_press_event:
- print_event_1 ("#<buttondown-event ", obj, printcharfun);
- break;
- case button_release_event:
- print_event_1 ("#<buttonup-event ", obj, printcharfun);
- break;
- case magic_event:
- print_event_1 ("#<magic-event ", obj, printcharfun);
- break;
- case pointer_motion_event:
- {
- char buf[100];
- sprintf (buf, "#<motion-event %d, %d",
- XEVENT (obj)->event.motion.x, XEVENT (obj)->event.motion.y);
- write_c_string (buf, printcharfun);
- break;
- }
- case process_event:
- {
- write_c_string ("#<process-event ", printcharfun);
- print_internal (XEVENT (obj)->event.process.process, printcharfun, 1);
- break;
- }
- case timeout_event:
- {
- write_c_string ("#<timeout-event ", printcharfun);
- print_internal (XEVENT (obj)->event.timeout.object, printcharfun, 1);
- break;
- }
- case empty_event:
- {
- write_c_string ("#<empty-event", printcharfun);
- break;
- }
- case misc_user_event:
- case eval_event:
- {
- write_c_string ("#<", printcharfun);
- if (XEVENT (obj)->event_type == misc_user_event)
- write_c_string ("misc-user", printcharfun);
- else
- write_c_string ("eval", printcharfun);
- write_c_string ("-event (", printcharfun);
- print_internal (XEVENT (obj)->event.eval.function, printcharfun, 1);
- write_c_string (" ", printcharfun);
- print_internal (XEVENT (obj)->event.eval.object, printcharfun, 1);
- write_c_string (")", printcharfun);
- break;
- }
- case dead_event:
- {
- write_c_string ("#<DEALLOCATED-EVENT", printcharfun);
- break;
- }
- default:
- {
- write_c_string ("#<UNKNOWN-EVENT-TYPE", printcharfun);
- break;
- }
- }
- write_c_string (">", printcharfun);
- }
-
- static int
- event_equal (Lisp_Object o1, Lisp_Object o2, int depth)
- {
- struct Lisp_Event *e1 = XEVENT (o1);
- struct Lisp_Event *e2 = XEVENT (o2);
-
- if (e1->event_type != e2->event_type) return 0;
- if (!EQ (e1->channel, e2->channel)) return 0;
- if (!EQ (e1->device, e2->device)) return 0;
- /* if (e1->timestamp != e2->timestamp) return 0; */
- switch (e1->event_type)
- {
- case process_event:
- return (EQ (e1->event.process.process,
- e2->event.process.process));
-
- case timeout_event:
- if (NILP (Fequal (e1->event.timeout.function,
- e2->event.timeout.function)))
- return 0;
- if (NILP (Fequal (e1->event.timeout.object,
- e2->event.timeout.object)))
- return 0;
- return 1;
-
- case key_press_event:
- return ((EQ (e1->event.key.keysym,
- e2->event.key.keysym)
- && (e1->event.key.modifiers
- == e2->event.key.modifiers)));
-
- case button_press_event:
- case button_release_event:
- return (((e1->event.button.button
- == e2->event.button.button)
- && (e1->event.button.modifiers
- == e2->event.button.modifiers)));
-
- case pointer_motion_event:
- return ((e1->event.motion.x == e2->event.motion.x
- && e1->event.motion.y == e2->event.motion.y));
-
- case misc_user_event:
- case eval_event:
- if (NILP (Fequal (e1->event.eval.function,
- e2->event.eval.function)))
- return 0;
- if (NILP (Fequal (e1->event.eval.object,
- e2->event.eval.object)))
- return 0;
- return 1;
- case magic_event:
- if (!EQ (e1->device, e2->device))
- return 0;
-
- #ifdef HAVE_X_WINDOWS
- /* XEvent is actually a union which means that we can't just use == */
- if (DEVICE_IS_X (XDEVICE (e1->device)))
- return (!memcmp ((XEvent *) &e1->event.magic.underlying_x_event,
- (XEvent *) &e2->event.magic.underlying_x_event,
- sizeof (e1->event.magic.underlying_x_event)));
- #endif
- #ifdef HAVE_NEXTSTEP
- if (DEVICE_IS_NS (XDEVICE (e1->device)))
- return (e1->event.magic.underlying_ns_event ==
- e2->event.magic.underlying_ns_event);
- #endif
- return (e1->event.magic.underlying_tty_event ==
- e2->event.magic.underlying_tty_event);
-
- case empty_event: /* Empty and deallocated events are equal. */
- case dead_event:
- return 1;
-
- default:
- abort ();
- return 0; /* not reached; warning suppression */
- }
- }
-
- static unsigned long
- event_hash (Lisp_Object obj, int depth)
- {
- struct Lisp_Event *e = XEVENT (obj);
- unsigned long hash;
-
- hash = HASH3 (e->event_type, LISP_HASH (e->channel), LISP_HASH (e->device));
- switch (e->event_type)
- {
- case process_event:
- return HASH2 (hash, LISP_HASH (e->event.process.process));
-
- case timeout_event:
- return HASH3 (hash, internal_hash (e->event.timeout.function, depth + 1),
- internal_hash (e->event.timeout.object, depth + 1));
-
- case key_press_event:
- return HASH3 (hash, LISP_HASH (e->event.key.keysym),
- e->event.key.modifiers);
-
- case button_press_event:
- case button_release_event:
- return HASH3 (hash, e->event.button.button, e->event.button.modifiers);
-
- case pointer_motion_event:
- return HASH3 (hash, e->event.motion.x, e->event.motion.y);
-
- case misc_user_event:
- case eval_event:
- return HASH3 (hash, internal_hash (e->event.eval.function, depth + 1),
- internal_hash (e->event.eval.object, depth + 1));
-
- case magic_event:
- #ifdef HAVE_X_WINDOWS
- if (DEVICE_IS_X (XDEVICE (e->device)))
- return
- HASH2 (hash,
- memory_hash (&e->event.magic.underlying_x_event,
- sizeof (e->event.magic.underlying_x_event)));
- #endif
- #ifdef HAVE_NEXTSTEP
- if (DEVICE_IS_NS (XDEVICE (e->device)))
- return
- HASH2 (hash,
- memory_hash (&e->event.magic.underlying_ns_event,
- sizeof (e->event.magic.underlying_ns_event)));
- #endif
- return
- HASH2 (hash,
- memory_hash (&e->event.magic.underlying_tty_event,
- sizeof (e->event.magic.underlying_tty_event)));
-
- case empty_event:
- case dead_event:
- return hash;
-
- default:
- abort ();
- }
-
- return 0;
- }
-
-
- DEFUN ("allocate-event", Fallocate_event, Sallocate_event, 0, 0, 0,
- "Return an empty event structure.\n\
- WARNING, the event object returned may be a reused one; see the function\n\
- `deallocate-event'.")
- ()
- {
- struct Lisp_Event *e;
- Lisp_Object event;
- if (event_resource)
- {
- e = event_resource;
- event_resource = event_next (e);
- XSETEVENT (event, e);
- }
- else
- {
- event = make_event ();
- e = XEVENT (event);
- }
- deinitialize_event (e);
- e->event_type = empty_event;
- set_event_next (e, 0);
- e->timestamp = 0;
- e->channel = Qnil;
- e->device = Qnil;
- return event;
- }
-
- DEFUN ("deallocate-event", Fdeallocate_event, Sdeallocate_event, 1, 1, 0,
- "Allow the given event structure to be reused.\n\
- You MUST NOT use this event object after calling this function with it.\n\
- You will lose. It is not necessary to call this function, as event\n\
- objects are garbage-collected like all other objects; however, it may\n\
- be more efficient to explicitly deallocate events when you are sure\n\
- that that is safe.")
- (event)
- Lisp_Object event;
- {
- struct Lisp_Event *e;
- CHECK_EVENT (event, 0);
-
- e = XEVENT (event);
- if (e->event_type == dead_event)
- error ("this event is already deallocated!");
-
- if (e->event_type > last_event_type)
- abort ();
-
- #if 0
- {
- int i;
- extern Lisp_Object Vlast_command_event;
- extern Lisp_Object Vlast_input_event, Vunread_command_event;
- extern Lisp_Object Vthis_command_keys, Vrecent_keys_ring;
-
- if (EQ (event, Vlast_command_event))
- abort ();
- if (EQ (event, Vlast_input_event))
- abort ();
- if (EQ (event, Vunread_command_event))
- abort ();
- for (i = 0; i < XVECTOR (Vthis_command_keys)->size; i++)
- if (EQ (event, vector_data (XVECTOR (Vthis_command_keys)) [i]))
- abort ();
- for (i = 0; i < XVECTOR (Vrecent_keys_ring)->size; i++)
- if (EQ (event, vector_data (XVECTOR (Vrecent_keys_ring)) [i]))
- abort ();
- }
- #endif /* 0 */
-
- if (e == event_resource)
- abort ();
- deinitialize_event (e);
- #ifndef ALLOC_NO_POOLS
- set_event_next (e, event_resource);
- event_resource = e;
- #endif
- return Qnil;
- }
-
- DEFUN ("copy-event", Fcopy_event, Scopy_event, 1, 2, 0,
- "Make a copy of the given event object.\n\
- If a second argument is given, the first event is copied into the second\n\
- and the second is returned. If the second argument is not supplied (or\n\
- is nil) then a new event will be made as with `allocate-event.' See also\n\
- the function `deallocate-event'.")
- (event1, event2)
- Lisp_Object event1, event2;
- {
- struct Lisp_Event *e1, *e2;
-
- CHECK_LIVE_EVENT (event1, 0);
- if (NILP (event2))
- event2 = Fallocate_event ();
- else CHECK_LIVE_EVENT (event2, 0);
- if (EQ (event1, event2))
- return signal_simple_continuable_error_2
- ("copy-event called with `eq' events", event1, event2);
- e1 = XEVENT (event1);
- e2 = XEVENT (event2);
-
- if (e1->event_type > last_event_type ||
- e2->event_type > last_event_type)
- abort ();
- {
- struct Lisp_Event *save_next = event_next (e2);
-
- *e2 = *e1;
- set_event_next (e2, save_next);
- return (event2);
- }
- }
-
-
-
- Lisp_Object QKbackspace, QKtab, QKlinefeed, QKreturn, QKescape,
- QKspace, QKdelete, QKnosymbol;
-
- int
- command_event_p (struct Lisp_Event *event)
- {
- switch (event->event_type)
- {
- case key_press_event:
- case button_press_event:
- case button_release_event:
- case misc_user_event:
- return (1);
- default:
- return (0);
- }
- }
-
-
- void
- character_to_event (Emchar c, struct Lisp_Event *event, struct device *d)
- {
- Lisp_Object k = Qnil;
- unsigned int m = 0;
- if (event->event_type == dead_event)
- error ("character-to-event called with a deallocated event!");
-
- #ifndef MULE
- c &= 255;
- #endif
- if (c > 127 && c <= 255)
- {
- int meta_flag = 1;
- if (d && DEVICE_IS_TTY (d))
- meta_flag = TTY_FLAGS (d).meta_key;
- switch (meta_flag)
- {
- case 0: /* ignore top bit; it's parity */
- c -= 128;
- break;
- case 1: /* top bit is meta */
- c -= 128;
- m = MOD_META;
- break;
- default: /* this is a real character */
- break;
- }
- }
- if (c < ' ') c += '@', m |= MOD_CONTROL;
- if (m & MOD_CONTROL)
- {
- switch (c)
- {
- case 'I': k = QKtab; m &= ~MOD_CONTROL; break;
- case 'J': k = QKlinefeed; m &= ~MOD_CONTROL; break;
- case 'M': k = QKreturn; m &= ~MOD_CONTROL; break;
- case '[': k = QKescape; m &= ~MOD_CONTROL; break;
- # if 0
- /* This is probably too controversial... */
- case 'H': k = QKbackspace; m &= ~MOD_CONTROL; break;
- # endif
- }
- if (c >= 'A' && c <= 'Z') c -= 'A'-'a';
- }
- else if (c == 127) k = QKdelete;
- else if (c == ' ') k = QKspace;
-
- event->event_type = key_press_event;
- event->channel = Qnil;
- event->timestamp = 0;
- if (d)
- XSETDEVICE (event->device, d);
- else
- event->device = Fselected_device ();
- event->event.key.keysym = (!NILP (k) ? k : make_number (c));
- event->event.key.modifiers = m;
- }
-
-
- /* This variable controls what character name -> character code mapping
- we are using. Window-system-specific code sets this to some symbol,
- and we use that symbol as the plist key to convert keysyms into 8-bit
- codes. In this way one can have several character sets predefined and
- switch them by changing this.
- */
- Lisp_Object Vcharacter_set_property;
-
- Emchar
- event_to_character (struct Lisp_Event *event,
- int allow_extra_modifiers,
- int allow_meta,
- int allow_non_ascii)
- {
- Emchar c = 0;
- if (event->event_type != key_press_event)
- {
- if (event->event_type == dead_event) abort ();
- return -1;
- }
- if (!allow_extra_modifiers &&
- event->event.key.modifiers & (MOD_SUPER|MOD_HYPER|MOD_ALT))
- return -1;
- if (INTP (event->event.key.keysym)) c = XINT (event->event.key.keysym);
- else if (EQ (event->event.key.keysym, QKbackspace)) c = '\b';
- else if (EQ (event->event.key.keysym, QKtab)) c = '\t';
- else if (EQ (event->event.key.keysym, QKlinefeed)) c = '\n';
- else if (EQ (event->event.key.keysym, QKreturn)) c = '\r';
- else if (EQ (event->event.key.keysym, QKescape)) c = 27;
- else if (EQ (event->event.key.keysym, QKspace)) c = ' ';
- else if (EQ (event->event.key.keysym, QKdelete)) c = 127;
-
- else if (!SYMBOLP (event->event.key.keysym))
- abort ();
- else if (allow_non_ascii && !NILP (Vcharacter_set_property))
- {
- /* Allow window-system-specific extensibility of keysym->code mapping */
- Lisp_Object code = Fget (event->event.key.keysym,
- Vcharacter_set_property,
- Qnil);
- if (!INTP (code))
- return -1;
- c = XINT (code);
- }
- else
- return -1;
-
- if (event->event.key.modifiers & MOD_CONTROL)
- {
- if (c >= 'a' && c <= 'z')
- c -= ('a' - 'A');
- else
- /* reject Control-Shift- keys */
- if (c >= 'A' && c <= 'Z' && !allow_extra_modifiers)
- return -1;
-
- if (c >= '@' && c <= '_')
- c -= '@';
- else if (c == ' ') /* C-space and C-@ are the same. */
- c = 0;
- else
- /* reject keys that can't take Control- modifiers */
- if (! allow_extra_modifiers) return -1;
- }
-
- if (event->event.key.modifiers & MOD_META)
- {
- if (! allow_meta) return -1;
- if (c & 0200) return -1; /* don't allow M-oslash (overlap) */
- #ifdef MULE
- if (c >= 256) return -1;
- #endif
- c |= 0200;
- }
- return c;
- }
-
-
- DEFUN ("event-to-character", Fevent_to_character, Sevent_to_character,
- 1, 4, 0,
- "Return the closest ASCII approximation to the given event object.\n\
- If the event isn't a keypress, this returns nil.\n\
- If the ALLOW-EXTRA-MODIFIERS argument is non-nil, then this is lenient in\n\
- its translation; it will ignore modifier keys other than control and meta,\n\
- and will ignore the shift modifier on those characters which have no\n\
- shifted ASCII equivalent (Control-Shift-A for example, will be mapped to\n\
- the same ASCII code as Control-A).\n\
- If the ALLOW-META argument is non-nil, then the Meta modifier will be\n\
- represented by turning on the high bit of the byte returned; otherwise, nil\n\
- will be returned for events containing the Meta modifier.\n\
- If the ALLOW-NON-ASCII argument is non-nil, then characters which are\n\
- present in the prevailing character set (see the `character-set-property'\n\
- variable) will be returned as their code in that character set, instead of\n\
- the return value being restricted to ASCII.\n\
- Note that specifying both ALLOW-META and ALLOW-NON-ASCII is ambiguous, as\n\
- both use the high bit; `M-x' and `oslash' will be indistinguishable.")
- (event, allow_extra_modifiers, allow_meta, allow_non_ascii)
- Lisp_Object event, allow_extra_modifiers, allow_meta, allow_non_ascii;
- {
- Emchar c;
- CHECK_LIVE_EVENT (event, 0);
- c = event_to_character (XEVENT (event),
- !NILP (allow_extra_modifiers),
- !NILP (allow_meta),
- !NILP (allow_non_ascii));
- return (c < 0 ? Qnil : make_number (c));
- }
-
-
- DEFUN ("character-to-event", Fcharacter_to_event, Scharacter_to_event, 1, 3, 0,
- "Converts a numeric ASCII value to an event structure, replete with\n\
- bucky bits. The character is the first argument, and the event to fill\n\
- in is the second. This function contains knowledge about what the codes\n\
- ``mean'' -- for example, the number 9 is converted to the character ``Tab'',\n\
- not the distinct character ``Control-I''.\n\
- \n\
- Note that CH does not have to be a numeric value, but can be a symbol such\n\
- as 'clear or a list such as '(control backspace).\n\
- \n\
- If the optional second argument is an event, it is modified; otherwise, a\n\
- new event object is created.\n\
- \n\
- Optional third arg DEVICE is the device to store in the event; this also\n\
- affects whether the high bit is interpreted as a meta key. A value of nil\n\
- means use the selected device but always treat the high bit as meta.\n\
- \n\
- Beware that character-to-event and event-to-character are not strictly\n\
- inverse functions, since events contain much more information than the\n\
- ASCII character set can encode.")
- (ch, event, device)
- Lisp_Object ch, event, device;
- {
- struct device *d;
-
- if (EQ (device, Qnil))
- d = 0;
- else
- d = get_device (device);
- if (NILP (event))
- event = Fallocate_event ();
- else
- CHECK_LIVE_EVENT (event, 0);
- if (CHARP (ch))
- character_to_event (XINT (ch), XEVENT (event), d);
- else if (CONSP (ch) || SYMBOLP (ch))
- key_desc_list_to_event (ch, event, 1);
- else
- CHECK_INT (ch, 0);
- return event;
- }
-
- void
- format_event_object (char *buf, struct Lisp_Event *event, int brief)
- {
- int mouse_p = 0;
- int mod = 0;
- Lisp_Object key;
-
- switch (event->event_type)
- {
- case key_press_event:
- {
- mod = event->event.key.modifiers;
- key = event->event.key.keysym;
- /* Hack. */
- if (! brief && INTP (key) &&
- mod & (MOD_CONTROL|MOD_META|MOD_SUPER|MOD_HYPER))
- {
- int k = XINT (key);
- if (k >= 'a' && k <= 'z')
- key = make_number (k - ('a'-'A'));
- else if (k >= 'A' && k <= 'Z')
- mod |= MOD_SHIFT;
- }
- break;
- }
- case button_release_event:
- mouse_p++;
- /* Fall through */
- case button_press_event:
- {
- mouse_p++;
- mod = event->event.button.modifiers;
- key = make_number (event->event.button.button + '0');
- break;
- }
- case magic_event:
- {
- CONST char *name = 0;
-
- #ifdef HAVE_X_WINDOWS
- if (DEVICE_IS_X (XDEVICE (Vselected_device)))
- name =
- x_event_name (event->event.magic.underlying_x_event.xany.type);
- #endif
- #ifdef HAVE_NEXTSTEP
- if (DEVICE_IS_NS (XDEVICE (Vselected_device)))
- name = ns_event_name (event->event.magic.underlying_ns_event);
- #endif
- if (name) strcpy (buf, name);
- else strcpy (buf, "???");
- return;
- }
- case pointer_motion_event: strcpy (buf, "motion"); return;
- case misc_user_event: strcpy (buf, "misc-user"); return;
- case eval_event: strcpy (buf, "eval"); return;
- case process_event: strcpy (buf, "process");return;
- case timeout_event: strcpy (buf, "timeout");return;
- case empty_event: strcpy (buf, "EMPTY-EVENT"); return;
- case dead_event: strcpy (buf, "DEAD-EVENT"); return;
- default:
- abort ();
- }
- #define modprint1(x) { strcpy (buf, (x)); buf += sizeof (x)-1; }
- #define modprint(x,y) { if (brief) modprint1 (y) else modprint1 (x) }
- if (mod & MOD_CONTROL) modprint ("control-", "C-");
- if (mod & MOD_META) modprint ("meta-", "M-");
- if (mod & MOD_SUPER) modprint ("super-", "S-");
- if (mod & MOD_HYPER) modprint ("hyper-", "H-");
- if (mod & MOD_ALT) modprint ("alt-", "A-");
- if (mod & MOD_SHIFT) modprint ("shift-", "Sh-");
- if (mouse_p)
- {
- modprint1 ("button");
- --mouse_p;
- }
- #undef modprint
- #undef modprint1
-
- if (INTP (key))
- {
- Bytecount len = emchar_to_charptr (XINT (key), (Bufbyte *) buf);
- buf[len] = 0;
- buf += len;
- }
- else if (SYMBOLP (key))
- {
- CONST char *str = 0;
- if (brief)
- {
- if (EQ (key, QKlinefeed)) str = "LFD";
- else if (EQ (key, QKtab)) str = "TAB";
- else if (EQ (key, QKreturn)) str = "RET";
- else if (EQ (key, QKescape)) str = "ESC";
- else if (EQ (key, QKdelete)) str = "DEL";
- else if (EQ (key, QKspace)) str = "SPC";
- else if (EQ (key, QKbackspace)) str = "BS";
- }
- if (str)
- {
- int i = strlen (str);
- memcpy (buf, str, i+1);
- str += i;
- }
- else
- {
- memcpy (buf, string_data (XSYMBOL (key)->name),
- string_length (XSYMBOL (key)->name) + 1);
- str += string_length (XSYMBOL (key)->name);
- }
- }
- else
- abort ();
- if (mouse_p)
- strncpy (buf, "up", 4);
- }
-
- DEFUN ("eventp", Feventp, Seventp, 1, 1, 0,
- "True if OBJECT is an event object.")
- (object)
- Lisp_Object object;
- {
- return ((EVENTP (object)) ? Qt : Qnil);
- }
-
- DEFUN ("event-live-p", Fevent_live_p, Sevent_live_p, 1, 1, 0,
- "True if OBJECT is an event object that has not been deallocated.")
- (object)
- Lisp_Object object;
- {
- return ((EVENTP (object) && XEVENT (object)->event_type != dead_event)
- ? Qt : Qnil);
- }
-
- /* DEFUN ("event-next", Fevent_next, Sevent_next, 1, 1, 0,
- * "Return the event object's `next' event, or nil if it has none.\n\
- * The `next-event' field is changed by calling `set-next-event'.")
- * (event)
- * Lisp_Object event;
- * {
- * struct Lisp_Event *e;
- * CHECK_LIVE_EVENT (event, 0);
- *
- * e = event_next (XEVENT (event));
- * if (!e)
- * return Qnil;
- * XSETEVENT (event, e);
- * return (event);
- * }
- *
- * DEFUN ("set-event-next", Fset_event_next, Sset_event_next, 2, 2, 0,
- * "Set the `next event' of EVENT to NEXT-EVENT.\n\
- * NEXT-EVENT must be an event object or nil.")
- * (event, next_event)
- * Lisp_Object event, next_event;
- * {
- * struct Lisp_Event *e;
- *
- * CHECK_LIVE_EVENT (event, 0);
- * if (NILP (next_event))
- * {
- * event_next (XEVENT (event)) = 0;
- * return (Qnil);
- * }
- *
- * CHECK_LIVE_EVENT (next_event, 1);
- * for (e = XEVENT (next_event); e; e = event_next (e))
- * {
- * QUIT;
- * if (e == XEVENT (event))
- * signal_error (Qerror,
- * list3 (build_string ("Cyclic event-next"),
- * event,
- * next_event));
- * }
- * event_next (XEVENT (event)) = XEVENT (next_event);
- * return (next_event);
- * }
- */
-
-
- #define EVENT_PRED(type) \
- return ((EVENTP (obj) && XEVENT (obj)->event_type == (type)) \
- ? Qt : Qnil)
-
- DEFUN ("key-press-event-p", Fkey_press_event_p, Skey_press_event_p, 1, 1, 0,
- "True if the argument is a key-press event object.")
- (obj)
- Lisp_Object obj;
- {
- EVENT_PRED (key_press_event);
- }
-
- DEFUN ("button-press-event-p", Fbutton_press_event_p, Sbutton_press_event_p,
- 1, 1, 0, "True if the argument is a mouse-button-press event object.")
- (obj)
- Lisp_Object obj;
- {
- EVENT_PRED (button_press_event);
- }
-
- DEFUN ("button-release-event-p", Fbutton_release_event_p,
- Sbutton_release_event_p, 1, 1, 0,
- "True if the argument is a mouse-button-release event object.")
- (obj)
- Lisp_Object obj;
- {
- if (EVENTP (obj) && XEVENT (obj)->event_type == button_release_event)
- return Qt;
- else
- return Qnil;
- }
- /* { EVENT_PRED (button_release_event); } */
-
- DEFUN ("button-event-p", Fbutton_event_p,
- Sbutton_event_p, 1, 1, 0,
- "True if the argument is a button-press or button-release event object.")
- (obj)
- Lisp_Object obj;
- {
- return ((EVENTP (obj)
- && (XEVENT (obj)->event_type == button_press_event ||
- XEVENT (obj)->event_type == button_release_event))
- ? Qt : Qnil);
- }
-
- DEFUN ("motion-event-p", Fmotion_event_p, Smotion_event_p, 1, 1, 0,
- "True if the argument is a mouse-motion event object.")
- (obj)
- Lisp_Object obj;
- {
- EVENT_PRED (pointer_motion_event);
- }
-
- DEFUN ("process-event-p", Fprocess_event_p, Sprocess_event_p, 1, 1, 0,
- "True if the argument is a process-output event object.")
- (obj)
- Lisp_Object obj;
- {
- EVENT_PRED (process_event);
- }
-
- DEFUN ("timeout-event-p", Ftimeout_event_p, Stimeout_event_p, 1, 1, 0,
- "True if the argument is a timeout event object.")
- (obj)
- Lisp_Object obj;
- {
- EVENT_PRED (timeout_event);
- }
-
- DEFUN ("misc-user-event-p", Fmisc_user_event_p, Smisc_user_event_p, 1, 1, 0,
- "True if the argument is a misc-user event object.\n\
- A misc-user event is a user event that is not a keypress or mouse click;\n\
- normally this means a menu selection or scrollbar action.")
- (obj)
- Lisp_Object obj;
- {
- EVENT_PRED (misc_user_event);
- }
-
- DEFUN ("eval-event-p", Feval_event_p, Seval_event_p, 1, 1, 0,
- "True if the argument is an `eval' event object.")
- (obj)
- Lisp_Object obj;
- {
- EVENT_PRED (eval_event);
- }
-
- DEFUN ("event-timestamp", Fevent_timestamp, Sevent_timestamp, 1, 1, 0,
- "Return the timestamp of the given event object.")
- (event)
- Lisp_Object event;
- {
- CHECK_LIVE_EVENT (event, 0);
- /* This junk is so that timestamps don't get to be negative, but contain
- as many bits as this particular emacs will allow.
- */
- return make_number (((1L << (VALBITS - 1)) - 1) &
- XEVENT (event)->timestamp);
- }
-
- #define CHECK_EVENT_TYPE(e,t1,sym) \
- { CHECK_LIVE_EVENT (e, 0); \
- if (XEVENT(e)->event_type != (t1)) \
- e = wrong_type_argument ((sym),(e)); \
- }
-
- #define CHECK_EVENT_TYPE2(e,t1,t2,sym) \
- { CHECK_LIVE_EVENT (e, 0); \
- if (XEVENT(e)->event_type != (t1) && XEVENT(e)->event_type != (t2)) \
- e = wrong_type_argument ((sym),(e)); \
- }
-
- DEFUN ("event-key", Fevent_key, Sevent_key, 1, 1, 0,
- "Return the KeySym of the given key-press event. This will be the\n\
- ASCII code of a printing character, or a symbol.")
- (event)
- Lisp_Object event;
- {
- CHECK_EVENT_TYPE (event, key_press_event, Qkey_press_event_p);
- return (XEVENT (event)->event.key.keysym);
- }
-
- /* #### This is X only but we need to redo some lisp code to get rid of it */
-
- DEFUN ("event-button", Fevent_button, Sevent_button, 1, 1, 0,
- "Return the button-number of the given mouse-button-press event.")
- (event)
- Lisp_Object event;
- {
- CHECK_EVENT_TYPE2 (event, button_press_event, button_release_event,
- Qbutton_event_p);
- #ifdef HAVE_WINDOW_SYSTEM
- return make_number (XEVENT (event)->event.button.button);
- #else /* !HAVE_WINDOW_SYSTEM */
- return Qzero;
- #endif /* !HAVE_WINDOW_SYSTEM */
- }
-
- DEFUN ("event-modifier-bits", Fevent_modifier_bits, Sevent_modifier_bits,
- 1, 1, 0,
- "Return a number representing the modifier keys which were down\n\
- when the given mouse or keyboard event was produced. See also the function\n\
- event-modifiers.")
- (event)
- Lisp_Object event;
- {
- again:
- CHECK_LIVE_EVENT (event, 0);
- if (XEVENT (event)->event_type == key_press_event)
- return make_number (XEVENT (event)->event.key.modifiers);
- else if (XEVENT (event)->event_type == button_press_event ||
- XEVENT (event)->event_type == button_release_event)
- return make_number (XEVENT (event)->event.button.modifiers);
- else if (XEVENT (event)->event_type == pointer_motion_event)
- return make_number (XEVENT (event)->event.motion.modifiers);
- else
- {
- event = wrong_type_argument (intern ("key-or-mouse-event-p"), event);
- goto again;
- }
- }
-
- DEFUN ("event-modifiers", Fevent_modifiers, Sevent_modifiers, 1, 1, 0,
- "Return a list of symbols, the names of the modifier keys\n\
- which were down when the given mouse or keyboard event was produced.\n\
- See also the function event-modifier-bits.")
- (event)
- Lisp_Object event;
- {
- int mod = XINT (Fevent_modifier_bits (event));
- Lisp_Object result = Qnil;
- if (mod & MOD_SHIFT) result = Fcons (Qshift, result);
- if (mod & MOD_ALT) result = Fcons (Qalt, result);
- if (mod & MOD_HYPER) result = Fcons (Qhyper, result);
- if (mod & MOD_SUPER) result = Fcons (Qsuper, result);
- if (mod & MOD_META) result = Fcons (Qmeta, result);
- if (mod & MOD_CONTROL) result = Fcons (Qcontrol, result);
- return result;
- }
-
- static int
- event_x_y_pixel_internal (Lisp_Object event, int *x, int *y, int relative)
- {
- struct window *w;
- struct frame *f;
-
- if (XEVENT (event)->event_type == pointer_motion_event)
- {
- *x = XEVENT (event)->event.motion.x;
- *y = XEVENT (event)->event.motion.y;
- }
- else if (XEVENT (event)->event_type == button_press_event ||
- XEVENT (event)->event_type == button_release_event)
- {
- *x = XEVENT (event)->event.button.x;
- *y = XEVENT (event)->event.button.y;
- }
- else
- return 0;
-
- f = XFRAME (Fevent_frame (event));
-
- if (relative)
- {
- w = find_window_by_pixel_pos (*x, *y, f->root_window);
-
- if (!w)
- return 1; /* #### What should really happen here. */
-
- *x -= w->pixel_left;
- *y -= w->pixel_top;
- }
- else
- {
- *y -= FRAME_REAL_TOP_TOOLBAR_HEIGHT (f);
- *x -= FRAME_REAL_LEFT_TOOLBAR_WIDTH (f);
- }
-
- return 1;
- }
-
- DEFUN ("event-window-x-pixel", Fevent_window_x_pixel, Sevent_window_x_pixel,
- 1, 1, 0,
- "Return the X position in pixels of the given mouse event.\n\
- The value returned is relative to the window the event occurred in.\n\
- This will signal an error if the event is not a mouse-motion, button-press,\n\
- or button-release event. See also `event-x-pixel'.")
- (event)
- Lisp_Object event;
- {
- int x, y;
-
- CHECK_LIVE_EVENT (event, 0);
-
- if (!event_x_y_pixel_internal (event, &x, &y, 1))
- return wrong_type_argument (Qmouse_event_p, event);
- else
- return make_number (x);
- }
-
- DEFUN ("event-window-y-pixel", Fevent_window_y_pixel, Sevent_window_y_pixel,
- 1, 1, 0,
- "Return the Y position in pixels of the given mouse event.\n\
- The value returned is relative to the window the event occurred in.\n\
- This will signal an error if the event is not a mouse-motion, button-press,\n\
- or button-release event. See also `event-y-pixel'.")
- (event)
- Lisp_Object event;
- {
- int x, y;
-
- CHECK_LIVE_EVENT (event, 0);
-
- if (!event_x_y_pixel_internal (event, &x, &y, 1))
- return wrong_type_argument (Qmouse_event_p, event);
- else
- return make_number (y);
- }
-
- DEFUN ("event-x-pixel", Fevent_x_pixel, Sevent_x_pixel,
- 1, 1, 0,
- "Return the X position in pixels of the given mouse event.\n\
- The value returned is relative to the frame the event occurred in.\n\
- This will signal an error if the event is not a mouse-motion, button-press,\n\
- or button-release event. See also `event-window-x-pixel'.")
- (event)
- Lisp_Object event;
- {
- int x, y;
-
- CHECK_LIVE_EVENT (event, 0);
-
- if (!event_x_y_pixel_internal (event, &x, &y, 0))
- return wrong_type_argument (Qmouse_event_p, event);
- else
- return make_number (x);
- }
-
- DEFUN ("event-y-pixel", Fevent_y_pixel, Sevent_y_pixel,
- 1, 1, 0,
- "Return the Y position in pixels of the given mouse event.\n\
- The value returned is relative to the frame the event occurred in.\n\
- This will signal an error if the event is not a mouse-motion, button-press,\n\
- or button-release event. See also `event-window-y-pixel'.")
- (event)
- Lisp_Object event;
- {
- int x, y;
-
- CHECK_LIVE_EVENT (event, 0);
-
- if (!event_x_y_pixel_internal (event, &x, &y, 0))
- return wrong_type_argument (Qmouse_event_p, event);
- else
- return make_number (y);
- }
-
- static int
- event_pixel_translation (Lisp_Object event, int *char_x, int *char_y,
- int *obj_x, int *obj_y,
- struct window **w, Bytind *bufp, Bytind *closest,
- Lisp_Object *obj)
- {
- int pix_x = 0;
- int pix_y = 0;
- int result;
- Lisp_Object frame;
-
- int ret_x, ret_y, ret_obj_x, ret_obj_y;
- struct window *ret_w;
- Bytind ret_bufp, ret_closest;
- Lisp_Object ret_obj;
-
- CHECK_LIVE_EVENT (event, 0);
- if (XEVENT (event)->event_type == pointer_motion_event)
- {
- pix_x = XEVENT (event)->event.motion.x;
- pix_y = XEVENT (event)->event.motion.y;
- frame = XEVENT (event)->channel;
- }
- else if (XEVENT (event)->event_type == button_press_event ||
- XEVENT (event)->event_type == button_release_event)
- {
- pix_x = XEVENT (event)->event.button.x;
- pix_y = XEVENT (event)->event.button.y;
- frame = XEVENT (event)->channel;
- }
- else
- wrong_type_argument (Qmouse_event_p, event);
-
- result = pixel_to_glyph_translation (XFRAME (frame), pix_x, pix_y,
- &ret_x, &ret_y, &ret_obj_x, &ret_obj_y,
- &ret_w, &ret_bufp, &ret_closest,
- &ret_obj);
-
- /* pixel_to_glyph_translation returns the following values:
-
- OVER_TOOLBAR: over one of the 4 frame toolbars
- OVER_MODELINE: over a modeline
- OVER_BORDER: over an internal border
- OVER_NOTHING: over the text area, but not over text
- OVER_OUTSIDE: outside of the frame border
- OVER_TEXT: over text in the text area
- */
-
- if (result == OVER_NOTHING || result == OVER_OUTSIDE)
- ret_bufp = 0;
- else if (ret_w && NILP (ret_w->buffer))
- /* Why does this happen? (Does it still happen?)
- I guess the window has gotten reused as a non-leaf... */
- ret_w = 0;
-
- /* #### pixel_to_glyph_translation() sometimes returns garbage...
- The word has type Lisp_Record (presumably meaning `extent') but the
- pointer points to random memory, often filled with 0, sometimes not.
- */
- if (!NILP (ret_obj) && !(EXTENTP (ret_obj) || TOOLBAR_BUTTONP (ret_obj)))
- abort ();
-
- if (char_x)
- *char_x = ret_x;
- if (char_y)
- *char_y = ret_y;
- if (obj_x)
- *obj_x = ret_obj_x;
- if (obj_y)
- *obj_y = ret_obj_y;
- if (w)
- *w = ret_w;
- if (bufp)
- *bufp = ret_bufp;
- if (closest)
- *closest = ret_closest;
- if (obj)
- *obj = ret_obj;
-
- return result;
- }
-
- DEFUN ("event-over-text-area-p", Fevent_over_text_area_p,
- Sevent_over_text_area_p, 1, 1, 0,
- "Given a mouse-motion, button-press, or button-release event, return\n\
- t if the event is over the text area of a window. Otherwise, return\n\
- nil. The modeline is not considered to be part of the text area.")
- (event)
- Lisp_Object event;
- {
- int result = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, 0);
-
- if (result == OVER_TEXT || result == OVER_NOTHING)
- return Qt;
- else
- return Qnil;
- }
-
- DEFUN ("event-over-modeline-p", Fevent_over_modeline_p, Sevent_over_modeline_p,
- 1, 1, 0,
- "Given a mouse-motion, button-press, or button-release event, return\n\
- t if the event is over the modeline of a window. Otherwise, return nil.")
- (event)
- Lisp_Object event;
- {
- int result = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, 0);
-
- if (result == OVER_MODELINE)
- return Qt;
- else
- return Qnil;
- }
-
- DEFUN ("event-over-border-p", Fevent_over_border_p, Sevent_over_border_p,
- 1, 1, 0,
- "Given a mouse-motion, button-press, or button-release event, return\n\
- t if the event is over an internal border. Otherwise, return nil.")
- (event)
- Lisp_Object event;
- {
- int result = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, 0);
-
- if (result == OVER_BORDER)
- return Qt;
- else
- return Qnil;
- }
-
- DEFUN ("event-over-toolbar-p", Fevent_over_toolbar_p, Sevent_over_toolbar_p,
- 1, 1, 0,
- "Given a mouse-motion, button-press, or button-release event, return\n\
- t if the event is over a toolbar. Otherwise, return nil.")
- (event)
- Lisp_Object event;
- {
- int result = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, 0);
-
- if (result == OVER_TOOLBAR)
- return Qt;
- else
- return Qnil;
- }
-
- DEFUN ("event-device", Fevent_device, Sevent_device, 1, 1, 0,
- "Return the device that the given event occurred on.\n\
- This will be nil for some types of events (e.g. eval events).")
- (event)
- Lisp_Object event;
- {
- CHECK_LIVE_EVENT (event, 0);
- return EVENT_DEVICE (XEVENT (event));
- }
-
- /* It would be possible to just use (window-frame (event-window event))
- but this gives better encapsulation and often makes the code easier
- to understand. */
- DEFUN ("event-frame", Fevent_frame, Sevent_frame, 1, 1, 0,
- "Given a mouse-motion, button-press, or button-release event, return\n\
- the frame on which that event occurred. This will be nil for non-mouse\n\
- events.")
- (event)
- Lisp_Object event;
- {
- CHECK_LIVE_EVENT (event, 0);
- if (FRAMEP (XEVENT (event)->channel))
- return (XEVENT (event)->channel);
- else
- return Qnil;
- }
-
- DEFUN ("event-window", Fevent_window, Sevent_window, 1, 1, 0,
- "Given a mouse motion, button press, or button release event, compute\n\
- and return the window on which that event occurred. This may be nil if\n\
- the event occurred in the border or over a toolbar. The modeline is\n\
- considered to be in the window it represents.")
- (event)
- Lisp_Object event;
- {
- struct window *w;
- Lisp_Object window;
-
- event_pixel_translation (event, 0, 0, 0, 0, &w, 0, 0, 0);
-
- if (!w)
- return Qnil;
- else
- {
- XSETWINDOW (window, w);
- return window;
- }
- }
-
- /* It would be possible to just use (window-buffer (event-window event))
- but this gives better encapsulation and often makes the code easier
- to understand. */
- DEFUN ("event-buffer", Fevent_buffer, Sevent_buffer, 1, 1, 0,
- "Given a mouse-motion, button-press, or button-release event, return\n\
- the buffer on which that event occurred. This will be nil for non-mouse\n\
- events. If event-over-text-area-p is nil, this will also be nil.")
- (event)
- Lisp_Object event;
- {
- Lisp_Object window = Fevent_window (event);
-
- if (WINDOWP (window))
- return XWINDOW (window)->buffer;
- else
- return Qnil;
- }
-
- DEFUN ("event-point", Fevent_point, Sevent_point, 1, 1, 0,
- "Return the character position of the given mouse-motion, button-press,\n\
- or button-release event. If the event did not occur over a window, or did\n\
- not occur over text, then this returns nil. Otherwise, it returns an index\n\
- into the buffer visible in the event's window.")
- (event)
- Lisp_Object event;
- {
- Bytind bufp;
- struct window *w;
-
- event_pixel_translation (event, 0, 0, 0, 0, &w, &bufp, 0, 0);
-
- if (!w)
- return Qnil;
- else if (!bufp)
- return Qnil;
- else
- return make_number (bufp);
- }
-
- DEFUN ("event-closest-point", Fevent_closest_point, Sevent_closest_point,
- 1, 1, 0,
- "Return the character position of the given mouse-motion, button-press,\n\
- or button-release event. If the event did not occur over a window or over\n\
- text, return the closest point to the location of the event. If the Y pixel\n\
- position overlaps a window and the X pixel position is to the left of that\n\
- window, the closest point is the beginning of the line containing the\n\
- Y position. If the Y pixel position overlaps a window and the X pixel\n\
- position is to the right of that window, the closest point is the end of the\n\
- line containing the Y position. If the Y pixel position is above a window,\n\
- return 0. If it is below a window, return the value of (window-end).")
- (event)
- Lisp_Object event;
- {
- Bytind bufp;
-
- event_pixel_translation (event, 0, 0, 0, 0, 0, 0, &bufp, 0);
-
- if (!bufp)
- return Qnil;
- else
- return make_number (bufp);
- }
-
- DEFUN ("event-x", Fevent_x, Sevent_x, 1, 1, 0,
- "Return the X position of the given mouse-motion, button-press, or\n\
- button-release event in characters. This is relative to the window the\n\
- event occurred over.")
- (event)
- Lisp_Object event;
- {
- int char_x;
-
- event_pixel_translation (event, &char_x, 0, 0, 0, 0, 0, 0, 0);
-
- return make_number (char_x);
- }
-
- DEFUN ("event-y", Fevent_y, Sevent_y, 1, 1, 0,
- "Return the Y position of the given mouse-motion, button-press, or\n\
- button-release event in characters. This is relative to the window the\n\
- event occurred over.")
- (event)
- Lisp_Object event;
- {
- int char_y;
-
- event_pixel_translation (event, 0, &char_y, 0, 0, 0, 0, 0, 0);
-
- return make_number (char_y);
- }
-
-
- DEFUN ("event-glyph-extent", Fevent_glyph_extent, Sevent_glyph_extent, 1, 1, 0,
- "If the given mouse-motion, button-press, or button-release event happened\n\
- on top of a glyph, this returns its extent. Otherwise return nil.")
- (event)
- Lisp_Object event;
- {
- Lisp_Object extent;
- struct window *w;
-
- event_pixel_translation (event, 0, 0, 0, 0, &w, 0, 0, &extent);
-
- if (!w)
- return Qnil;
- else if (EXTENTP (extent))
- return extent;
- else
- return Qnil;
- }
-
- /* You could just as easily use event-glyph-extent but we include this
- for consistency. It could easily be implemented in elisp but none
- of the rest of the event- functions are so we'll just stick it
- here. */
- DEFUN ("event-over-glyph-p", Fevent_over_glyph_p, Sevent_over_glyph_p,
- 1, 1, 0,
- "Given a mouse-motion, button-press, or button-release event, return\n\
- t if the event is over a glyph. Otherwise, return nil.")
- (event)
- Lisp_Object event;
- {
- if (NILP (Fevent_glyph_extent (event)))
- return Qnil;
- else
- return Qt;
- }
-
- DEFUN ("event-glyph-x-pixel", Fevent_glyph_x_pixel, Sevent_glyph_x_pixel,
- 1, 1, 0,
- "Given a mouse-motion, button-press, or button-release event over a glyph,\n\
- return the X position of the pointer relative to the upper left of the\n\
- glyph. If the event is not over a glyph, return nil.")
- (event)
- Lisp_Object event;
- {
- Lisp_Object extent;
- struct window *w;
- int obj_x;
-
- event_pixel_translation (event, 0, 0, &obj_x, 0, &w, 0, 0, &extent);
-
- if (w && EXTENTP (extent))
- return make_number (obj_x);
- else
- return Qnil;
- }
-
- DEFUN ("event-glyph-y-pixel", Fevent_glyph_y_pixel, Sevent_glyph_y_pixel,
- 1, 1, 0,
- "Given a mouse-motion, button-press, or button-release event over a glyph,\n\
- return the Y position of the pointer relative to the upper left of the\n\
- glyph. If the event is not over a glyph, return nil.")
- (event)
- Lisp_Object event;
- {
- Lisp_Object extent;
- struct window *w;
- int obj_y;
-
- event_pixel_translation (event, 0, 0, 0, &obj_y, &w, 0, 0, &extent);
-
- if (w && EXTENTP (extent))
- return make_number (obj_y);
- else
- return Qnil;
- }
-
- DEFUN ("event-toolbar-button", Fevent_toolbar_button, Sevent_toolbar_button,
- 1, 1, 0,
- "If the given mouse-motion, button-press, or button-release event happened\n\
- on top of a toolbar button, return the button. Otherwise, return nil.")
- (event)
- Lisp_Object event;
- {
- Lisp_Object button;
- int result;
-
- result = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, &button);
-
- if (result == OVER_TOOLBAR)
- {
- if (TOOLBAR_BUTTONP (button))
- return button;
- else
- return Qnil;
- }
- else
- return Qnil;
- }
-
- DEFUN ("event-process", Fevent_process, Sevent_process, 1, 1, 0,
- "Return the process of the given process-output event.")
- (event)
- Lisp_Object event;
- {
- CHECK_EVENT_TYPE (event, process_event, Qprocess_event_p);
- return (XEVENT (event)->event.process.process);
- }
-
- DEFUN ("event-function", Fevent_function, Sevent_function, 1, 1, 0,
- "Return the callback function of the given timeout, misc-user, or eval event.")
- (event)
- Lisp_Object event;
- {
- CHECK_LIVE_EVENT (event, 0);
- switch (XEVENT (event)->event_type)
- {
- case timeout_event:
- return (XEVENT (event)->event.timeout.function);
- case misc_user_event:
- case eval_event:
- return (XEVENT (event)->event.eval.function);
- default:
- return wrong_type_argument (intern ("timeout-or-eval-event-p"), event);
- }
- }
-
- DEFUN ("event-object", Fevent_object, Sevent_object, 1, 1, 0,
- "Return the callback function argument of the given timeout, misc-user, or\n\
- eval event.")
- (event)
- Lisp_Object event;
- {
- again:
- CHECK_LIVE_EVENT (event, 0);
- switch (XEVENT (event)->event_type)
- {
- case timeout_event:
- return (XEVENT (event)->event.timeout.object);
- case misc_user_event:
- case eval_event:
- return (XEVENT (event)->event.eval.object);
- default:
- event = wrong_type_argument (intern ("timeout-or-eval-event-p"), event);
- goto again;
- }
- }
-
-
- /************************************************************************/
- /* initialization */
- /************************************************************************/
-
- void
- syms_of_events (void)
- {
- defsubr (&Scharacter_to_event);
- defsubr (&Sevent_to_character);
-
- defsubr (&Sallocate_event);
- defsubr (&Sdeallocate_event);
- defsubr (&Scopy_event);
- defsubr (&Seventp);
- defsubr (&Sevent_live_p);
- defsubr (&Skey_press_event_p);
- defsubr (&Sbutton_press_event_p);
- defsubr (&Sbutton_release_event_p);
- defsubr (&Sbutton_event_p);
- defsubr (&Smotion_event_p);
- defsubr (&Sprocess_event_p);
- defsubr (&Stimeout_event_p);
- defsubr (&Smisc_user_event_p);
- defsubr (&Seval_event_p);
-
- defsubr (&Sevent_timestamp);
- defsubr (&Sevent_key);
- defsubr (&Sevent_button);
- defsubr (&Sevent_modifier_bits);
- defsubr (&Sevent_modifiers);
- defsubr (&Sevent_x_pixel);
- defsubr (&Sevent_y_pixel);
- defsubr (&Sevent_window_x_pixel);
- defsubr (&Sevent_window_y_pixel);
- defsubr (&Sevent_over_text_area_p);
- defsubr (&Sevent_over_modeline_p);
- defsubr (&Sevent_over_border_p);
- defsubr (&Sevent_over_toolbar_p);
- defsubr (&Sevent_device);
- defsubr (&Sevent_frame);
- defsubr (&Sevent_window);
- defsubr (&Sevent_buffer);
- defsubr (&Sevent_point);
- defsubr (&Sevent_closest_point);
- defsubr (&Sevent_x);
- defsubr (&Sevent_y);
- defsubr (&Sevent_glyph_extent);
- defsubr (&Sevent_over_glyph_p);
- defsubr (&Sevent_glyph_x_pixel);
- defsubr (&Sevent_glyph_y_pixel);
- defsubr (&Sevent_toolbar_button);
- defsubr (&Sevent_process);
- defsubr (&Sevent_function);
- defsubr (&Sevent_object);
-
- defsymbol (&Qeventp, "eventp");
- defsymbol (&Qevent_live_p, "event-live-p");
- defsymbol (&Qkey_press_event_p, "key-press-event-p");
- defsymbol (&Qbutton_event_p, "button-event-p");
- defsymbol (&Qmouse_event_p, "mouse-event-p");
- defsymbol (&Qprocess_event_p, "process-event-p");
- }
-
- void
- vars_of_events (void)
- {
- DEFVAR_LISP ("character-set-property", &Vcharacter_set_property,
- "A symbol used to look up the 8-bit character of a keysym.\n\
- To convert a keysym symbol to an 8-bit code, as when that key is\n\
- bound to self-insert-command, we will look up the property that this\n\
- variable names on the property list of the keysym-symbol. The window-\n\
- system-specific code will set up appropriate properties and set this\n\
- variable.");
- Vcharacter_set_property = Qnil;
-
- event_resource = 0;
-
- QKbackspace = KEYSYM ("backspace");
- QKtab = KEYSYM ("tab");
- QKlinefeed = KEYSYM ("linefeed");
- QKreturn = KEYSYM ("return");
- QKescape = KEYSYM ("escape");
- QKspace = KEYSYM ("space");
- QKdelete = KEYSYM ("delete");
- QKnosymbol = KEYSYM ("NoSymbol");
-
- staticpro (&QKbackspace);
- staticpro (&QKtab);
- staticpro (&QKlinefeed);
- staticpro (&QKreturn);
- staticpro (&QKescape);
- staticpro (&QKspace);
- staticpro (&QKdelete);
- staticpro (&QKnosymbol);
- }
-